package cc.iotkit.plugins.wzr.service;

import cc.iotkit.common.enums.ErrCode;
import cc.iotkit.common.exception.BizException;
import cc.iotkit.plugin.core.thing.IDevice;
import cc.iotkit.plugin.core.thing.IThingService;
import cc.iotkit.plugin.core.thing.actions.ActionResult;
import cc.iotkit.plugin.core.thing.actions.down.*;
import com.gitee.starblues.bootstrap.annotation.AutowiredType;
import io.netty.handler.codec.mqtt.MqttQoS;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.mqtt.MqttClient;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.configurationprocessor.json.JSONException;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.stereotype.Service;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 *  mq下行处理
 *  网关上线离线心跳
 *  组网三步通知
 *  设备增加删除
 *  设备上线，下线，心跳
 *  群组增加，删除，修改
 *  定时任务增加，删除，修改
 */
@Slf4j
@Service
public class MqttDevice implements IDevice {

    @Setter
    private MqttClient client;
    @Autowired
    @AutowiredType(AutowiredType.Type.MAIN_PLUGIN)
    private IThingService thingService;

    @Override
    public ActionResult config(DeviceConfig action) {
        return ActionResult.builder().code(0).reason("").build();
    }

    @Override
    public ActionResult propertyGet(PropertyGet action) {
        String topic = String.format("/sys/%s/%s/c/service/property/get", action.getProductKey(), action.getDeviceName());
        return send(
                topic,
                new JsonObject()
                        .put("id", action.getId())
                        .put("method", "thing.service.property.get")
                        .put("params", action.getKeys())
        );
    }
    @Override
    public ActionResult propertySet(PropertySet action) {
        // 网关mac处理"17468460718080 0000c0a81227 0000203"截取"0000c0a81227"
        String gwmac = (String) action.getParams().get("gwmac");
        if (gwmac == null || gwmac.equals("")) {
            return ActionResult.builder().code(1).reason("网关mac为空").build();
        }
        if (((String) action.getParams().get("gwmac")).length()>12) {
            gwmac = gwmac.substring(14, 26);
        }
        // String topic = String.format("v5/0000C0A81227/gateway/rpc", action.getDeviceName());
        String topic = String.format("v5/%s/gateway/rpc", gwmac.toUpperCase());
        JsonObject data = new JsonObject();
        data.put("id", action.getId());
        data.put("method", "unicast");
        JsonObject params = new JsonObject();
        params.put("cmd", "set");
        JsonObject aia = new JsonObject();
        aia.put("await", 1);
        JsonObject args = new JsonObject();
        JsonObject dp = new JsonObject();
        if (action.getParams().get("pa0")!=null) {
            dp.put("pa0", Integer.parseInt(action.getParams().get("pa0").toString()));
        }
        if (action.getParams().get("duty0")!=null) {
            dp.put("duty0", Integer.parseInt(action.getParams().get("duty0").toString()));
        }
        args.put("dp", dp);
        params.put("aia", aia);
        params.put("args", args);
        data.put("params", params);
        JsonObject pload = new JsonObject();
        pload.put("device", action.getDeviceName());
        pload.put("data", data);
        return send(
                topic,
                pload
        );
    }

    @Override
    public ActionResult groupPropertySet(GroupPropertySet action) {
        return null;
    }

    @Override
    public ActionResult serviceInvoke(ServiceInvoke action){
        String topic = String.format("/sys/%s/%s/c/service/%s", action.getProductKey(), action.getDeviceName(), action.getName());
        //如果服务是自组网
        log.info("当前服务名称："+action.getName());
        log.info("当前服务内容："+action.getParams());
        if (action.getName().equals("netSearch")) {
            String top1 = String.format("v5/%s/devices/me/rpc/request/1", action.getDeviceName());
            JsonObject pld = new JsonObject("{\"method\":\"local\",\"params\":{\"cmd\":\"call\",\"aia\":{\"await\":0},\"args\":{\"fcn\":\"netSearch\",\"input\":{\"duration\":10,\"type\":1,\"state\":1}}}}");
//            JsonObject pload1 = new JsonObject();
//            pload1.put("method","local");
//            JsonObject params = new JsonObject();
//            params.put("cmd","call");
//            params.put("aia", new JsonObject().put("await",0));
//            params.put("args", new JsonObject().put("fcn","netSearch"));
//            JsonObject input = new JsonObject();
//            input.put("duration",10);
//            input.put("type",0);
//            input.put("state",1);
//            params.put("input",input);
//            pload1.put("params",params);
            if(send(top1,pld).getCode()!=0){
                return ActionResult.builder().code(1).reason("组网命令top1发送失败").build();
            }
        }
        // 查询已入网子设备总数
        if (action.getName().equals("netNum")) {
            String top2 = String.format("v5/%s/devices/me/rpc/request/2",action.getDeviceName());
            String pload2 = "{\"method\":\"local\",\"params\":{\"cmd\":\"call\",\"aia\":{\"await\":0},\"args\":{\"fcn\":\"netNum\",\"input\":{\"type\":0}}}}";
            if(send(top2,new JsonObject(pload2)).getCode()!=0){
                return ActionResult.builder().code(1).reason("组网命令top2发送失败").build();
            }
        }
        // 自组网搜索设备类型
        if (action.getName().equals("netSearchProductKey")) {
            String top1 = String.format("v5/%s/devices/me/rpc/request/1", action.getDeviceName());
            JsonObject pld = new JsonObject("{\"method\":\"local\",\"params\":{\"cmd\":\"call\",\"aia\":{\"await\":0},\"args\":{\"fcn\":\"netSearch\",\"input\":{\"type\":1,\"state\":2}}}}");
            if(send(top1,pld).getCode()!=0){
                return ActionResult.builder().code(1).reason("组网命令top1+发送失败").build();
            }
        }
        // 查询已入网并识别到设备类型的子设备总数(含设备类型)
        if (action.getName().equals("netNumProductKey")) {
            String top2 = String.format("v5/%s/devices/me/rpc/request/2",action.getDeviceName());
            String pload2 = "{\"method\":\"local\",\"params\":{\"cmd\":\"call\",\"aia\":{\"await\":0},\"args\":{\"fcn\":\"netNum\",\"input\":{\"type\":1}}}}";
            if(send(top2,new JsonObject(pload2)).getCode()!=0){
                return ActionResult.builder().code(1).reason("组网命令top2+发送失败").build();
            }
        }
        //查询组网结果(含设备类型)
        if (action.getName().equals("selectNet")) {
            // 根据节点数量, 循环下发获取节点信息, 每次下发获取十个
            Integer toponum = Integer.valueOf(action.getParams().get("toponum").toString());
            ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
            try {
                for (int i = 1; i <= toponum; i += 10) {
                    int start = i;
                    int cnt = 10;
                    // 调度器异步延迟执行, 每个延迟loop秒执行, 实际效果每个下发间隔2秒
                    int loop = ((i - 1) / 10 + 1) * 2;
                    scheduler.schedule(() -> {
                        String top3 = String.format("v5/%s/devices/me/rpc/request/3",action.getDeviceName());
                        String pload3 = String.format("{\"method\":\"local\",\"params\":{\"cmd\":\"call\",\"aia\":{\"await\":0},\"args\":{\"fcn\":\"netInfo\",\"input\":{\"type\":1,\"start\":%s,\"cnt\":%s}}}}",start,cnt);
                        send(top3,new JsonObject(pload3));
                        log.info("下发获取节点信息 -> gw:{}, start:{}, cnt:{}", action.getDeviceName(), start, cnt);
                    }, loop, TimeUnit.SECONDS);
                }
            } catch (Exception e) {
                log.error("下发获取节点信息失败 -> gw:{}", action.getDeviceName(), e);
                return ActionResult.builder().code(1).reason("组网命令top3发送失败").build();
            } finally {
                scheduler.shutdown(); // 确保线程池资源释放
            }
            return ActionResult.builder().code(0).reason("").build();
//            String top3 = String.format("v5/%s/devices/me/rpc/request/3",action.getDeviceName());
//            String pload3 = String.format("{\"method\":\"local\",\"params\":{\"cmd\":\"call\",\"aia\":{\"await\":0},\"args\":{\"fcn\":\"netInfo\",\"input\":{\"type\":1,\"start\":%s,\"cnt\":%s}}}}",action.getParams().get("start"),action.getParams().get("cnt"));
//            if(send(top3,new JsonObject(pload3)).getCode()!=0){
//                return ActionResult.builder().code(1).reason("组网命令top3发送失败").build();
//            }
        }
        //查询组网拓扑节点信息
        if (action.getName().equals("topoInfo")) {
            String top3 = String.format("v5/%s/devices/me/rpc/request/3",action.getDeviceName());
            String pload3 = String.format("{\"method\":\"local\",\"params\":{\"cmd\":\"call\",\"aia\":{\"await\":0},\"args\":{\"fcn\":\"topoInfo\",\"input\":{\"start\":%s,\"cnt\":%s}}}}",action.getParams().get("start"),action.getParams().get("cnt"));
            if(send(top3,new JsonObject(pload3)).getCode()!=0){
                return ActionResult.builder().code(1).reason("组网命令拓扑节点信息发送失败").build();
            }
        }
        //如果是设置群组
        if (action.getName().equals("pgmac")) {
            String topc = String.format("v5/%s/devices/me/attributes",action.getDeviceName());
            JsonArray ja = new JsonArray();
            if(send(topc,new JsonObject()
                    .put("_version-mgmac",ja)
                    .put(String.format("_pgmac-%s",action.getParams().get("pgmac")),action.getParams().get("dmc"))).getCode()!=0){
                return ActionResult.builder().code(1).reason("设置群组失败").build();
            }
        }
        //设备与网关mac增删改
        if (action.getName().equals("pvid")) {
            String topgw = String.format("v5/%s/devices/me/attributes", action.getDeviceName());
            JsonArray ja = new JsonArray();
            ja.add(action.getParams().get("gwmac"));
            if (send(topgw, new JsonObject()
                    .put("_version-pvid", ja)
                    .put("_pvid-" + action.getParams().get("gwmac"), action.getParams().get("devmac"))
            ).getCode() != 0) {
                return ActionResult.builder().code(1).build();
            }
        }
        if(action.getName().equals("whInfo")){
            String topgw =String.format("v5/%s/devices/me/rpc/request/5",action.getDeviceName());
            String pload = String.format("{\"method\":\"local\",\"params\":{\"cmd\":\"call\",\"aia\":{\"await\":0},\"args\":{\"fcn\":\"whInfo\",\"input\":{\"start\":%s,\"cnt\":%s}}}}",0,500);
            if(send(topgw,new JsonObject(pload)).getCode()!=0){
                return ActionResult.builder().code(1).build();
            }
        }
        if (action.getName().equals("resetCfg")){
            String topgw =String.format("v5/%s/devices/me/rpc/request/6",action.getDeviceName());
            String pload = "{\"method\":\"local\",\"params\":{\"cmd\":\"call\",\"aia\":{\"await\":0},\"args\":{\"fcn\":\"resetCfg\"}}}";
            if(send(topgw,new JsonObject(pload)).getCode()!=0){
                return ActionResult.builder().code(1).build();
            }
        }
        //网关系统重启(组网后不重启, 这垃圾网关不上报设备状态)
        if (action.getName().equals("rebootSystem")){
            String topgw =String.format("v5/%s/devices/me/rpc/request/7",action.getDeviceName());
            String pload = "{\"method\":\"local\",\"params\":{\"cmd\":\"call\",\"aia\":{\"await\":0},\"args\":{\"fcn\":\"rebootSystem\"}}}";
            if(send(topgw,new JsonObject(pload)).getCode()!=0){
                return ActionResult.builder().code(1).build();
            }
        }
        //设置终端属性gatewayrpc
        if (action.getName().equals("gatewayrpc")){
            String topgw =String.format("v5/%s/devices/me/rpc/request/8",action.getDeviceName());
            String pload =String.format("{\"method\":\"groupcast\",\"params\":{\"cmd\":\"set\",\"aia\":{\"await\":0},\"pgmacId\":1,\"args\":{\"dp\":{\"pa0\":%s,\"duty0\":%s}}}}",action.getParams().get("percentage"),action.getParams().get("workstate"));
            if(send(topgw,new JsonObject(pload)).getCode()!=0){
                return ActionResult.builder().code(1).build();
            }
        }

        return send(
                topic,
                new JsonObject()
                        .put("id", action.getId())
                        .put("method", "thing.service." + action.getName())
                        .put("params", action.getParams())
        );
    }

    private ActionResult send(String topic, JsonObject payload) {
        try {
            client.publish(topic, payload.toBuffer(), MqttQoS.AT_LEAST_ONCE, false, false);
            return ActionResult.builder().code(0).reason("").build();
        } catch (BizException e) {
            return ActionResult.builder().code(e.getCode()).reason(e.getMessage()).build();
        } catch (Exception e) {
            return ActionResult.builder().code(ErrCode.UNKNOWN_EXCEPTION.getKey()).reason(e.getMessage()).build();
        }
    }

    /**
     * 网关开始组网，自动将发现的设备发送到云端，默认值发现200个
     */

}
